/*!
 * Curator - Gallery Management
 * Requires pagination, imageset, and replication jQuery Plugins
 * 
 * Copyright (c) 2009 Eric Garside (http://eric.garside.name)
 * Dual licensed under:
 * 	MIT: http://www.opensource.org/licenses/mit-license.php
 *	GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
 */
(function($){
	
	/** Dependency Tracking **/
	if (!$.pagination) throw 'CURATOR_DEPENDENCY_PAGINATION'; 
	if (!$.imageSet) throw 'CURATOR_DEPENDENCY_IMAGESET';
	if (!$.replication) throw 'CURATOR_DEPENDENCY_REPLICATION';

	/** jQuery Entry Point **/
	$.curator = {
		defaultPageSize: 10,
		alwaysMakeCurrent: true,
		
		/** Internal Event Delegation **/
		isReady: false,
		delegate: $('<a></a>').bind('ready', function(){$.curator.isReady=true}),
		ready: function(f){
			if (typeof f != 'function') return;
			
			if ($.curator.isReady) f.call($.curator.delegate);
			else $.curator.delegate.bind('ready', f);
		},
		
		/** Active Plugins **/
		activeImageSet: null,
		activeReplicator: null,
		activePaginator: null,
		// Called by the active setters to determine if Curator is ready
		check: function(){ if (!$.curator.isReady && $.curator.activeImageSet && $.curator.activeReplicator && $.curator.activePaginator) $.curator.delegate.trigger('ready') },
		
		/** imageSet **/
		// Storage of imageSets by name
		imageset: {},
		// Number of imagesets
		imagesets: 0,
		// Callback for alerting curator that a new imageSet is ready
		imageSetCreated: function(){ 
			var self = $(this).data('self');
			if ($.curator.alwaysMakeCurrent || !$.curator.activeImageSet) $.curator.activateImageSet(self.title);
		},
		// Manufacture a new ImageSet, add the curator callback, index the set
		newImageSet: function(group, images, options, size){
			options = options||{};
			options.chunkSize = size||$.curator.defaultPageSize;
			var set = $.curator.imageset[group] = new $.Image(group, options).ready($.curator.imageSetCreated);
			$.curator.populateImageSet.call(set, images);
			$.curator.imagesets++;
			return set.index();
		},
		// Define the activeImageSet
		activateImageSet: function(group, current){
			if ($.curator.reapplyPage){
				current = $.curator.reapplyPage;
				$.curator.reapplyPage = 0;
			} else current = current||0;
			
			if (!$.curator.imageset[group]){
				$.curator.reapplyPage = current;
				$.curator.createImageSet.apply($.curator, arguments);
				return false;
			}
			
			var set = $.curator.activeImageSet = $.curator.imageset[group];
			$.curator.delegate.trigger('group-change', [group, current]);
			if (set && $.curator.activePaginator) $.curator.updatePaginator(set.chunks, current);
			$.curator.check();
			return true;
		},
		recalculateChunkSize: function(size){
			$.each($.curator.imageset, function(){ this.chunkSize = size; this.index(); })
		},
		
		/** Replicator **/
		// Storage of Replicator by name
		replicator: {},
		// Track the number of replicators in the system
		replicators: 0,
		// Callback for alerting curator that a new Replicator is ready
		replicatorCreated: function(){ if (!$.curator.activeReplicator) $.curator.activateReplicator(this.group) },
		// Manufacture a new Replicator, add the curator callback, create the default size
		createReplicator: function(template, container, rules, size, group){
			group = group||'curator';
			size = size||$.curator.defaultPageSize;
			$.curator.replicators++;
			var rep = $.curator.replicator[group] = new $.Replicator(group, template, container, rules);
			return rep.setReplications(size, $.curator.replicatorCreated);
		},
		// Define a Replicator
		activateReplicator: function(group){ $.curator.activeReplicator = $.curator.replicator[group]||null; $.curator.check() },
		resetReplicationSize: function(size, cb){
			var rp = $.curator.replicators;
			$.each($.curator.replicator, function(){ 
				this.setReplications(size, function(){ 
					rp--; if (rp == 0 && typeof cb == 'function') cb.call($.curator.activeReplicator) 
				})
			})
		},
		
		/** Pagination **/
		// Storage of paginatiors
		paginator: {},
		// Number of paginators
		paginators: 0,
		// Create a new paginator
		createPaginator: function(selector, options, group){
			options = options||{};
			group = group||'curator';
			var ais = $.curator.activeImageSet;
			options.pages = ais?ais.chunks:0;
			$.curator.paginator[group] = $(selector).pagination(group, options, $.curator.pageChange);
			if (!$.curator.activePaginator) $.curator.activatePaginator(group);
			$.curator.paginators++;
		},
		// Callback for paginator events (Drives most of Curator's automation)
		pageChange: function(group){
			$.curator.delegate.trigger('page-change', [this, group]);
			var ar = $.curator.activeReplicator;
			if (ar) $.curator.render($.curator.activeImageSet.toChunk(this), ar);
		},
		// Define a Paginator
		activatePaginator: function(group){ $.curator.activePaginator = $.curator.paginator[group]||null; $.curator.check() },
		// Set the number of pages for the paginator
		updatePaginator: function(pages, current){ $.curator.activePaginator.pagination('renumber', {pages: pages, current: current}) },
		
		/** User Overwriteable Functions **/
		createImageSet: function(){},	// How to fetch the data for an imageset. Should call newImageSet().
		populateImageSet: function(){},	// How to add images into the set. "this" is the ImageSet to add to.
		render: function(){},			// How curator interacts with the Replicator
		
		/** Internals **/
		// Quick method to extend Curator functionality
		program: function(overwrites){ $.extend($.curator, overwrites); return $.curator },
		// Update the number of elements per page, and re-render the page
		resetPageSize: function(size, cb){
			$.curator.defaultPageSize = size;  
			$.curator.resetReplicationSize(size, function(){
				$.curator.recalculateChunkSize(size);
				if (typeof cb == 'function') cb.call($.curator);
			});
		}
	};
	
})(jQuery);
